// 多组件库的国际化和本地项目国际化兼容
import { type I18n, createI18n } from "vue-i18n";
import type { App, WritableComputedRef, ref } from "vue";
import { responsiveStorageNameSpace } from "@/config";
import { storageLocal, isObject } from "@pureadmin/utils";

// element-plus国际化
import enLocale from "element-plus/es/locale/lang/en";
import zhLocale from "element-plus/es/locale/lang/zh-cn";

const siphonI18n = (function () {
    // 仅初始化一次国际化配置
    const cache = Object.fromEntries(
        Object.entries(
            import.meta.glob("../../locales/*.json", { eager: true }) // 匹配 JSON 文件
        ).map(([key, value]: any) => {
            const matched = key.match(/([A-Za-z0-9-]+)\.json$/i)[1]; // 提取语言前缀（如 zh-CN）
            return [matched, value.default]; // 存储语言配置
        })
    );
    return (prefix = "zh-CN") => {
        return cache[prefix]; // 返回对应语言的配置对象
    };
})();

export const localesConfigs = {
    zh: {
        ...siphonI18n("zh-CN"),
        ...zhLocale
    },
    en: {
        ...siphonI18n("en"),
        ...enLocale
    }
};

/** 获取对象中所有嵌套对象的key键，并将它们用点号分割组成字符串 */
function getObjectKeys(obj) {
    const stack = [];
    const keys: Set<string> = new Set();

    stack.push({ obj, key: "" });

    while (stack.length > 0) {
        const { obj, key } = stack.pop();

        for (const k in obj) {
            const newKey = key ? `${key}.${k}` : k;

            if (obj[k] && isObject(obj[k])) {
                stack.push({ obj: obj[k], key: newKey });
            } else {
                // keys.add(key);
                keys.add(newKey);
            }
        }
    }

    return keys;
}

/** 将展开的key缓存 */
const keysCache: Map<string, Set<string>> = new Map();
/**
 * 获取扁平化的国际化资源对象
 * @param {string} prefix - 语言前缀，默认为"zh-CN"
 * @returns {Object} 返回扁平化的国际化资源对象
 */
const flatI18n = (prefix = "zh-CN") => {
    // 尝试从缓存中获取指定语言前缀的国际化资源
    let cache = keysCache.get(prefix);
    // 如果缓存中没有，则获取并处理国际化资源
    if (!cache) {
        // 获取指定语言的国际化资源对象，并扁平化处理
        cache = getObjectKeys(siphonI18n(prefix));
        // 将处理后的资源存入缓存
        keysCache.set(prefix, cache);
    }
    // 返回缓存或新处理的国际化资源对象
    return cache;
};

/**
 * 国际化转换工具函数（自动读取根目录locales文件夹下文件进行国际化匹配）
 * @param message message
 * @returns 转化后的message
 */
export function transformI18n(message: any = "") {
    if (!message) {
        return "";
    }

    // 处理存储动态路由的title,格式 {zh:"",en:""}
    if (typeof message === "object") {
        const locale: string | WritableComputedRef<string> | any =
            i18n.global.locale;
        return message[locale?.value];
    }

    const key = message.match(/(\S*)\./)?.input;

    if (key && flatI18n("zh-CN").has(key)) {

        // 使用i18n全局对象进行翻译，通过call方法指定语言环境
        return i18n.global.t.call(i18n.global.locale, message);
    } else if (!key && Object.hasOwn(siphonI18n("zh-CN"), message)) {

        // 兼容非嵌套形式的国际化写法
        return i18n.global.t.call(i18n.global.locale, message);
    } else {
        return message;
    }
}

/** 此函数只是配合i18n Ally插件来进行国际化智能提示，并无实际意义（只对提示起作用），如果不需要国际化可删除 */
export const $t = (message: any) => {
    if (!message) {
        return "";
    }

    // 处理存储动态路由的title,格式 {zh:"",en:""}
    if (typeof message === "object") {
        const locale: string | WritableComputedRef<string> | any =
            i18n.global.locale;
        return message[locale?.value];
    }

    const key = message.match(/(\S*)\./)?.input;

    if (key && flatI18n("zh-CN").has(key)) {

        // 使用i18n全局对象进行翻译，通过call方法指定语言环境
        return i18n.global.t.call(i18n.global.locale, message);
    } else if (!key && Object.hasOwn(siphonI18n("zh-CN"), message)) {

        // 兼容非嵌套形式的国际化写法
        return i18n.global.t.call(i18n.global.locale, message);
    } else {
        return message;
    }
}

// 国际化配置项
export const i18n: I18n = createI18n({
    legacy: false,  // 是否使用旧版模式，设为false使用新版vue-i18n
    locale:         // 当前使用的语言环境
        storageLocal().getItem<StorageConfigs>(  // 从本地存储中获取语言配置
            `${responsiveStorageNameSpace()}locale`  // 获取存储命名空间下的locale配置
        )?.locale,  // 如果获取到则使用获取到的值，否则默认使用"zh"(中文)
    fallbackLocale: "zh",  // 当指定语言翻译不存在时使用的后备语言
    messages: localesConfigs  // 语言翻译消息配置对象
});

// setTimeout(() => {
//     console.log('i18n.ts初始化语言=>', storageLocal().getItem<StorageConfigs>(  // 从本地存储中获取语言配置
//         `${responsiveStorageNameSpace()}locale`  // 获取存储命名空间下的locale配置
//     )?.locale);
// }, 500)

export function useI18n(app: App) {
    app.use(i18n);
}